package com.tsing.ipcliveserver.controller;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tsing.ipcliveserver.exception.BadRequestException;
import com.tsing.ipcliveserver.util.TranscodingCommandUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * HTTP-FLV控制器
 *
 * @author TheTsing
 */
@Controller
public class LiveController {

    @Value("${config.location}")
    private String configPath;

    @Value("${http-flv.max-connections:8}")
    private Integer httpFlvMaxConnections;

    private static final Logger log = LoggerFactory.getLogger(LiveController.class);

    private static final AtomicInteger CONNECTION_COUNT = new AtomicInteger(0);

    @GetMapping(value = "/live", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
    public ResponseEntity<Resource> live(@RequestParam String url) {
        if (!StringUtils.hasText(url)) {
            throw new BadRequestException("Url cannot be empty");
        }
        String cmd = TranscodingCommandUtil.generateTranscodingCommand(url);
        Process process;
        try {
            process = Runtime.getRuntime().exec(cmd);
        } catch (Exception e) {
            throw new BadRequestException("Transcoding error");
        }
        if (CONNECTION_COUNT.get() >= httpFlvMaxConnections) {
            process.destroy();
            throw new BadRequestException("Maximum connection limit exceeded");
        }
        CONNECTION_COUNT.incrementAndGet();
        new Thread(() -> {
            try (BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {
                String line;
                while ((line = errorReader.readLine()) != null) {
                    log.error("Transcoding error ==> " + line);
                }
            } catch (Exception ignored) {
            } finally {
                CONNECTION_COUNT.decrementAndGet();
            }
        }).start();
        return ResponseEntity.ok(new InputStreamResource(process.getInputStream()));
    }

    @GetMapping(value = "/list")
    public ResponseEntity<String> list() {
        try {
            String jsonContent = new String(Files.readAllBytes(Paths.get(configPath)));
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode jsonNode = objectMapper.readTree(jsonContent);
            return ResponseEntity.ok(jsonNode.toString());
        } catch (Exception e) {
            throw new BadRequestException("JSON file read failure");
        }
    }

}
